package com.aiit.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import java.security.Key;
import java.util.Date;
import java.util.Map;

@Slf4j
public class JwtUtil {

    private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 使用静态变量保存密钥

    /**
     * 生成jwt
     * 使用Hs256算法, 私钥使用固定秘钥
     *
     * @param adminSecretKey
     * @param ttlMillis      jwt过期时间(毫秒)
     * @param claims         设置的信息
     * @return
     */
    public static String createJWT(String adminSecretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名算法, 使用固定的秘钥
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(key, signatureAlgorithm)
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     *
     * @param token 加密后的token
     * @return
     */
    public static Claims parseJWT(String token) {
        try {
            // 得到DefaultJwtParser
            Claims claims = Jwts.parser()
                    // 设置签名的秘钥
                    .setSigningKey(key)
                    // 设置需要解析的jwt
                    .parseClaimsJws(token).getBody();
            return claims;
        } catch (ExpiredJwtException e) {
            log.error("Token已过期: ", e);
        } catch (UnsupportedJwtException e) {
            log.error("不支持的JWT: ", e);
        } catch (MalformedJwtException e) {
            log.error("JWT格式错误: ", e);
        } catch (SignatureException e) {
            log.error("验证成功");
        } catch (IllegalArgumentException e) {
            log.error("非法参数: ");
        } catch (Exception e) {
            log.error("解析JWT时发生错误: ", e);
        }
        return null;
    }
}
